﻿// Decompiled with JetBrains decompiler
// Type: Netick.Client
// Assembly: Netick, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 6726ECA1-C773-4CF7-8952-E81B30D93B52
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.dll
// XML documentation location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Runtime\Netick.xml

using System;

#nullable disable
namespace Netick;

public class Client : NetworkPeer
{
  public readonly ClientConnection ConnectedServer;
  internal bool HasInvokedOnConnectedToServer;
  internal Tick ConnectionTick = Tick.InvalidTick;

  public override float InKBps => this.ConnectedServer.BytesIn.AvgKBps;

  public override float OutKBps => this.ConnectedServer.BytesOut.AvgKBps;

  public bool IsConnected { get; private set; }

  public Client(NetickEngine engine)
    : base(engine)
  {
    this.ConnectedServer = new ClientConnection((short) 0, this.Engine);
  }

  internal override void Reset()
  {
    base.Reset();
    this.Engine._simulationTick = new Tick(10);
    this.Engine._snapshotTick = new Tick(10);
  }

  internal override void Start(int port)
  {
    if (this.Engine.IsLoggingEnabled)
      NetickLogger.Log(this.Engine, (object) "Started.");
    this.Transport?.Run(RunMode.Client, port);
  }

  internal override void Stop()
  {
    this.DisconnectInternal(true);
    this.Transport?.ForceUpdate();
    this.Reset();
    this.IsConnected = false;
    base.Stop();
  }

  public void Connect(int port, string ip, byte[] connectionData = null, int connectionDataLength = 0)
  {
    if (!this.Engine.IsRunning || this.IsConnected || this.Engine.StartMode == NetickStartMode.SinglePlayer)
      return;
    this.Transport.Connect(ip, port, connectionData, connectionDataLength);
  }

  public void Disconnect() => this.DisconnectInternal(false);

  private void DisconnectInternal(bool isLocalShutdown)
  {
    if (this.Engine.StartMode == NetickStartMode.SinglePlayer || !this.IsConnected)
      return;
    this.OnDisconnected(this.ConnectedServer.TransportConnection, isLocalShutdown ? TransportDisconnectReason.Shutdown : TransportDisconnectReason.DisconnectedByClient);
    this.Transport.Disconnect(this.ConnectedServer.TransportConnection);
  }

  internal override void Update() => this.ConnectedServer.Update(this.Engine.Timer.RawDeltaTime);

  public override void OnConnectFailed(ConnectionFailedReason reason)
  {
    this.Engine._gameEngine.OnConnectFailed(reason);
    if (!this.Engine.IsLoggingEnabled)
      return;
    if (reason == ConnectionFailedReason.Refused)
      NetickLogger.Log(this.Engine, (object) "Connection to server refused.");
    else
      NetickLogger.Log(this.Engine, (object) "Connection to server timed out.");
  }

  public override void OnConnected(TransportConnection peer)
  {
    this.Engine._internalReplicator.PlayersReplicator.Reset();
    this.Engine._internalReplicator.MismatchChecker.Reset();
    this.Reset();
    this.IsConnected = true;
    this.ConnectionTick = new Tick(10);
    this.ConnectedServer.OnConnected(peer);
    this.ConnectedServer.TransportConnection = peer;
    this.ConnectedServer.IsReady = true;
    this.Engine._cliSim.Reset();
    this.Engine._remoteInterpolation.Reset();
    this.ConnectedServer.RTT.ResetTo((double) Math.Max(this.Engine.FixedDeltaTime * (float) this.Engine.Config.ServerDivisor, 0.05f));
    try
    {
      this.Engine._gameEngine.OnPeerConnected((NetworkConnection) this.ConnectedServer);
    }
    catch (Exception ex)
    {
      NetickLogger.LogError(this.Engine, (object) ex);
    }
  }

  internal void TryInvokeOnConnectedToServer()
  {
    if (this.HasInvokedOnConnectedToServer)
      return;
    if (this.Engine.IsLoggingEnabled)
      NetickLogger.Log(this.Engine, (object) ("Connected to server: " + this.Engine.Client.ConnectedServer.EndPoint?.ToString()));
    this.Engine._remoteInterpolation.Reset();
    this.Engine._timer.Start();
    this.Engine._cliSim.ResetSimulationData();
    this.HasInvokedOnConnectedToServer = true;
    this.Engine._gameEngine.OnConnectedToServer();
  }

  public override void OnDisconnected(
    TransportConnection peer,
    TransportDisconnectReason transportDisconnectReason)
  {
    if (!this.IsConnected)
      return;
    this.HasInvokedOnConnectedToServer = false;
    this.IsConnected = false;
    this.ConnectionTick = Tick.InvalidTick;
    if (this.Engine.IsLoggingEnabled)
      NetickLogger.Log(this.Engine, (object) ("Disconnected from server: " + peer.EndPoint?.ToString()));
    try
    {
      this.Engine._gameEngine.OnPeerDisconnected((NetworkConnection) this.ConnectedServer, transportDisconnectReason);
      this.Engine._gameEngine.OnDisconnectedFromServer(transportDisconnectReason);
    }
    catch (Exception ex)
    {
      NetickLogger.LogError(this.Engine, (object) ex);
    }
    this.ConnectedServer.OnDisconnected(transportDisconnectReason, false);
    this.Reset();
  }

  public override void Receive(
    TransportConnection connection,
    BitBuffer reader,
    TransportDeliveryMethod transportDeliveryMethod)
  {
    if (!this.IsConnected || (double) this.Engine.SimulatedLossIn > 0.0 && this.Engine._rand.NextDouble() < (double) this.Engine.SimulatedLossIn)
      return;
    try
    {
      this.ConnectedServer.ReadPacket(reader, transportDeliveryMethod);
    }
    catch (Exception ex)
    {
      if (this.Engine.IsLoggingEnabled)
        NetickLogger.LogError((object) $"Netick: disconnected due to bad packet from the server: {ex}");
      this.Engine.DisconnectFromServer();
    }
    reader.Clear();
  }
}
